package main

import (
	"bytes"
	"fmt"
	"github.com/beego/beego/v2/core/logs"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/beego/beego/v2/server/web/context"
	"go1/controllers"
	"go1/lib/flake"
	"go1/lib/log_lib"
	_ "go1/routers"
	"io"
	"log"
	"reflect"
	"runtime"
	"strings"
)

var appName, _ = beego.AppConfig.String("appname")

func main() {
	log.SetFlags(log.Lshortfile | log.LstdFlags)
	//sql := cbdb.BuildSelect([]string{"a", "b", "c"})
	//log.Println(sql)
	log_lib.InitLog()
	beego.BConfig.RecoverPanic = true
	beego.BConfig.RecoverFunc = RecoverPanic
	//beego.InsertFilter("/*", beego.BeforeStatic, setRequestId)
	beego.InsertFilterChain("/*", FilterFunc)
	beego.Run("127.0.0.1:8080")
}

func FilterFunc(next beego.FilterFunc) beego.FilterFunc {
	return func(ctx *context.Context) {
		setRequestId(ctx)
		LogRequest(ctx)
		next(ctx)
	}
}

func LogRequest(c *context.Context) {
	cc := c.Request.Body
	body, _ := io.ReadAll(cc)
	reqID := c.Input.Header("X-Request-Id")
	authorization := c.Input.Header("Authorization")
	logs.Info("RequestId: %v URL: %v, Method: %s, Body: %v, authorization: %s", reqID, c.Request.URL, c.Request.Method, string(body), authorization)
	bf := bytes.NewBuffer(body)
	c.Request.Body = io.NopCloser(bf)
}

func setRequestId(ctx *context.Context) {
	reqID := ctx.Input.Header("X-Request-Id")
	if len(reqID) == 0 {
		ctx.Request.Header.Add("X-Request-Id", flake.GetString())
	}
}

func RecoverPanic(ctx *context.Context, config *beego.Config) {
	if err := recover(); err != nil {
		var stack string
		for i := 1; ; i++ {
			_, file, line, ok := runtime.Caller(i)
			if !ok {
				break
			}
			if i == 1 {
				continue
			}
			if strings.Contains(file, appName) {
				if i > 2 {
					stack += ","
				}
				stack += fmt.Sprintf("%s:%d", file, line)
			} else {
				break
			}
		}
		cc := ctx.Request.Body
		body, _ := io.ReadAll(cc)
		reqID := ctx.Input.Header("X-Request-Id")
		var tip string
		if reflect.TypeOf(err) == reflect.TypeOf("") {
			tip = fmt.Sprintf("%s", err)
		} else {
			tip = "unexpected_error"
		}
		logs.Error("RequestId: %s URL: %s, Method: %v; Body: %v | Error: %v | Stack: %v", reqID, ctx.Input.URI(), ctx.Input.Method(), string(body), err, stack)
		_ = ctx.Output.JSON(controllers.ReplyPanic(ctx.Input.URL(), tip), true, true)
		//if ctx.Output.Status != 0 {
		//	ctx.ResponseWriter.WriteHeader(ctx.Output.Status)
		//} else {
		//	ctx.ResponseWriter.WriteHeader(500)
		//}
	}
}
